🧱 C Programlama ile Kuyruk (Queue) Veri Yapısı Nasıl Oluşturulur?
Kuyruk (Queue), yazılım geliştirme sürecinde sıklıkla kullanılan temel bir veri yapısıdır.
Bu rehberde, C programlama dilinde Kuyruk (Queue) yapısının nasıl oluşturulacağını, dizi tabanlı ve iki yığın (stack) temelli yöntemleriyle öğreneceksiniz.
Kuyruklar İlk Giren İlk Çıkar (FIFO) prensibiyle çalışır. Bu da, kuyrukta ilk eklenen elemanın ilk çıkarıldığı anlamına gelir — tıpkı bir bilet sırasındaki insanlar gibi 🎟️
🎯 Bu Rehberde Ne Öğreneceksiniz?
- FIFO mantığını ve kuyruk yapısının nasıl çalıştığını öğreneceksiniz.
enqueue()vedequeue()işlemlerini kod örnekleriyle uygulayacaksınız.- Dizi tabanlı ve iki yığın (stack) temelli kuyruk yöntemlerini kıyaslayacaksınız.
- Kuyrukların işletim sistemlerinden ağ programlamaya kadar birçok kullanım alanını keşfedeceksiniz.
- Bellek yönetimi ve yaygın hatalardan kaçınma yollarını öğreneceksiniz.
🧠 Kuyruk (Queue) Nedir?
Kuyruk, doğrusal (linear) bir veri yapısıdır.
Veriler arka (Rear) uçtan eklenir ve ön (Front) uçtan çıkarılır.
Bu mantık, "İlk Giren İlk Çıkar (FIFO – First In, First Out)" kuralına dayanır.
🎟️ Gerçek Hayat Örneği:
Bir banka kuyruğunda önce gelen müşteri önce hizmet alır.
Kuyruk veri yapısı da bu davranışı bilgisayar belleğinde taklit eder.
⚙️ Kuyrukta Kullanılan Temel İşlemler
| İşlem | Açıklama | Zaman Karmaşıklığı |
|---|---|---|
| enqueue() | Kuyruğun sonuna (rear) eleman ekler | O(1) |
| dequeue() | Kuyruğun başından (front) eleman çıkarır | O(1) |
| isEmpty() | Kuyruk boş mu kontrol eder | O(1) |
| isFull() | Kuyruk dolu mu kontrol eder (dizi tabanlı) | O(1) |
| front() | İlk elemanı görüntüler | O(1) |
| rear() | Son elemanı görüntüler | O(1) |
🔹 1️⃣ Dizi (Array) Tabanlı Kuyruk Uygulaması
Bu en basit kuyruk yaklaşımıdır.
Kuyruk dizinin başında başlar ve arka kısmında yeni elemanlar eklenir.
📐 Çalışma Mantığı
FrontveRearbaşlangıçta-1olarak ayarlanır.enqueue: Dizi dolu değilse,Rearartırılır ve eleman eklenir.dequeue: Kuyruk boş değilse,Frontartırılır ve eleman çıkarılır.- Son eleman çıkarıldığında
FrontveReartekrar-1yapılır.
🧩 Örnek Kod (Dizi Tabanlı Kuyruk)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
int queue[SIZE];
int Front = -1;
int Rear = -1;
void enqueue(int value) {
if (Rear == SIZE - 1) {
printf("Hata: Kuyruk Tasmasi (Overflow)\n");
return;
}
if (Front == -1) Front = 0;
queue[++Rear] = value;
printf("%d kuyruga eklendi.\n", value);
}
void dequeue() {
if (Front == -1 || Front > Rear) {
printf("Hata: Kuyruk Bos (Underflow)\n");
return;
}
printf("%d kuyruktan cikarildi.\n", queue[Front++]);
}
void display() {
if (Front == -1 || Front > Rear) {
printf("Kuyruk bos.\n");
return;
}
printf("Kuyruk: ");
for (int i = Front; i <= Rear; i++)
printf("%d ", queue[i]);
printf("\n");
}
int main() {
enqueue(10);
enqueue(20);
enqueue(30);
display();
dequeue();
display();
return 0;
}
💡 Bu örnek, sabit boyutlu bir diziyle temel FIFO mantığını uygular.
🔹 2️⃣ İki Yığın (Stack) ile Kuyruk Uygulaması
C dilinde yığın (stack) yapısını kullanarak da kuyruk davranışı taklit edilebilir. Bu yöntemde iki yığın (S1 ve S2) kullanılır.
📦 Yöntem 1: Enqueue İşlemi Maliyetli (O(n))
Yeni eleman eklenmeden önce S1’deki tüm elemanlar S2’ye aktarılır.
Yeni eleman S1’e eklenir.
S2’deki elemanlar tekrar S1’e taşınır. 👉 Dequeue işlemi artık O(1) hızında olur.
⚡ Yöntem 2: Dequeue İşlemi Maliyetli (O(n))
Enqueue işlemi sadece S1’e yapılır (O(1)).
Dequeue sırasında, eğer S2 boşsa tüm elemanlar S1’den S2’ye aktarılır.
Böylece FIFO düzeni korunur.
💡 Bu yöntem, yığınların LIFO yapısını tersine çevirerek FIFO davranışı elde eder.
🔹 3️⃣ Bağlı Liste (Linked List) ile Kuyruk Simülasyonu
Dinamik bellek sayesinde kuyruk boyutu sınırsız hale gelir. Aşağıdaki örnek, müşteri sırasını simüle eden bir bağlı liste kuyruğu uygular.
#include <stdio.h>
#include <stdlib.h>
typedef struct Dugum {
int data;
struct Dugum* next;
} Dugum;
void enqueue(Dugum** front, Dugum** rear, int data) {
Dugum* yeni = (Dugum*)malloc(sizeof(Dugum));
yeni->data = data;
yeni->next = NULL;
if (*rear == NULL) *front = *rear = yeni;
else {
(*rear)->next = yeni;
*rear = yeni;
}
}
int dequeue(Dugum** front, Dugum** rear) {
if (*front == NULL) {
printf("Kuyruk bos\n");
return -1;
}
Dugum* temp = *front;
int data = temp->data;
*front = (*front)->next;
if (*front == NULL) *rear = NULL;
free(temp);
return data;
}
int main() {
Dugum* front = NULL;
Dugum* rear = NULL;
enqueue(&front, &rear, 1);
enqueue(&front, &rear, 2);
enqueue(&front, &rear, 3);
printf("Cikarilan: %d\n", dequeue(&front, &rear));
printf("Cikarilan: %d\n", dequeue(&front, &rear));
return 0;
}
💡 Bağlı liste, sabit boyut sınırlaması olmayan kuyruk yapıları için idealdir.
⚙️ Kuyrukların Gerçek Kullanım Alanları
| Uygulama Alanı | Açıklama |
|---|---|
| CPU Zamanlaması | İşletim sistemlerinde işlemler sırayla yürütülür. |
| BFS Algoritması | Graf aramalarında düğümler seviye seviye gezilir. |
| Ağ İletişimi | Veri paketleri sırayla gönderilip alınır. |
| Simülasyonlar | Banka ve market gibi gerçek dünya modellerinde sıra yönetimi. |
| Görev Yönetimi | Görevler, öncelik sırasına göre işlenir. |
🧩 Yaygın Hatalar ve İpuçları
| Hata | Sebep | Çözüm |
|---|---|---|
| Overflow (Taşma) | Dolu kuyruğa ekleme yapılması | isFull() ile kontrol et |
| Underflow (Eksiklik) | Boş kuyruğa çıkarma yapılması | isEmpty() kontrolü ekle |
| Bellek Sızıntısı | free() unutulması | Her dequeue işleminden sonra serbest bırak |
| Yanlış Pointer Güncellemesi | Front ve Rear yanlış atanması | Her işlem sonunda doğru pointer ataması yap |
| Sonsuz Döngü | NULL kontrolünün eksik olması | if (Front == NULL) kontrolü ekle |
⚖️ Dizi vs. Bağlı Liste Kuyruk Karşılaştırması
| Özellik | Dizi (Array) Kuyruk | Bağlı Liste Kuyruk |
|---|---|---|
| Boyut | Sabit | Dinamik |
| Bellek Kullanımı | Daha verimli | Fazla (pointer maliyeti) |
| Hız | Cache dostu, daha hızlı | Bellek dağınıklığı nedeniyle biraz yavaş |
| Overflow Riski | Var | Yok |
| Uygulama Karmaşıklığı | Basit | Orta |
❓ Sıkça Sorulan Sorular (SSS)
1️⃣ C dilinde yerleşik bir Kuyruk yapısı var mı?
Hayır, C dilinde yerleşik bir kuyruk yoktur. Dizi veya bağlı listeyle manuel uygulanır.
2️⃣ En kolay kuyruk yöntemi hangisidir?
Bağlı liste yöntemi en esnek ve kolay olanıdır. Taşma riski yoktur.
3️⃣ Dizi tabanlı kuyruğun dezavantajı nedir?
Sabit boyut ve boş alanların tekrar kullanılamaması. Bu nedenle dairesel kuyruk tercih edilir.
4️⃣ Kuyruk ve Yığın farkı nedir?
Kuyruk: FIFO (İlk Giren İlk Çıkar) Yığın: LIFO (Son Giren İlk Çıkar)
5️⃣ İki yığınla kuyruk neden kullanılır?
Yığınların sadece tek uçtan erişimi olduğu için, FIFO sırasını taklit etmek için iki yığın birlikte kullanılır.
🚀 Sonuç
Bu rehberde C programlama dilinde Kuyruk (Queue) veri yapısının nasıl oluşturulacağını adım adım öğrendin. Artık dizi, bağlı liste veya yığın kullanarak farklı kuyruk yapıları geliştirebilir ve FIFO mantığını projelerinde güvenle uygulayabilirsin.
💬 Şimdi sıra sende! Rabisu Bulut Platformu’nda hemen bir C projesi oluştur, kendi kuyruk yapını test et ve performans farklarını gözlemle. ⚡